﻿using System;
using System.Diagnostics;
using System.IO;

namespace SfsTools.Core
{
    /// <summary>
    /// Base class for file entries.
    /// </summary>
    internal abstract class BaseFileEntry : FileSystemObjectEntry
    {
        #region Properties

        /// <summary>
        /// Gets or sets the starting block number of the file in the data area.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">The argument <paramref name="value"/> is out of valid range.</exception>
        public Int64 FirstBlock
        {
            [DebuggerStepThrough]
            get
            {
                using (BinaryReader br = new BinaryReader(new MemoryStream(FBuffer, false)))
                {
                    br.BaseStream.Position = 0x0A;
                    return br.ReadInt64();
                }
            }
            [DebuggerStepThrough]
            set
            {
                if (value < 0)
                    throw new ArgumentOutOfRangeException("value");
                using (BinaryWriter bw = new BinaryWriter(new MemoryStream(FBuffer, true)))
                {
                    bw.BaseStream.Position = 0x0A;
                    bw.Write(value);
                }
            }
        }

        /// <summary>
        /// Gets or sets the ending block number of the file in the data area.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">The argument <paramref name="value"/> is out of valid range.</exception>
        public Int64 LastBlock
        {
            [DebuggerStepThrough]
            get
            {
                using (BinaryReader br = new BinaryReader(new MemoryStream(FBuffer, false)))
                {
                    br.BaseStream.Position = 0x12;
                    return br.ReadInt64();
                }
            }
            [DebuggerStepThrough]
            set
            {
                if (value < 0)
                    throw new ArgumentOutOfRangeException("value");
                using (BinaryWriter bw = new BinaryWriter(new MemoryStream(FBuffer, true)))
                {
                    bw.BaseStream.Position = 0x12;
                    bw.Write(value);
                }
            }
        }

        /// <summary>
        /// Gets or sets the size of the file in bytes.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">The argument <paramref name="value"/> is out of valid range.</exception>
        public Int64 FileSize
        {
            [DebuggerStepThrough]
            get
            {
                using (BinaryReader br = new BinaryReader(new MemoryStream(FBuffer, false)))
                {
                    br.BaseStream.Position = 0x1A;
                    return br.ReadInt64();
                }
            }
            [DebuggerStepThrough]
            set
            {
                if (value < 0)
                    throw new ArgumentOutOfRangeException("value");
                using (BinaryWriter bw = new BinaryWriter(new MemoryStream(FBuffer, true)))
                {
                    bw.BaseStream.Position = 0x1A;
                    bw.Write(value);
                }
            }
        }

        /// <summary>
        /// Gets or sets the name of the file.
        /// </summary>
        /// <exception cref="ArgumentNullException">The argument <paramref name="value"/> is <see langword="null"/>.</exception>
        public Byte[] Name
        {
            [DebuggerStepThrough]
            get
            {
                byte[] buffer = new byte[30];
                Array.Copy(FBuffer, 0x22, buffer, 0, 30);
                return buffer;
            }
            [DebuggerStepThrough]
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                Array.Copy(value, 0, FBuffer, 0x22, Math.Min(30, value.Length));
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Copies the contents of this entry to <paramref name="buffer"/>.
        /// </summary>
        /// <param name="buffer">The buffer to copy the contents to.</param>
        /// <param name="index">The starting byte index.</param>
        [DebuggerStepThrough]
        public override void CopyTo(byte[] buffer, int index)
        {
            Array.Copy(FBuffer, 0x22, buffer, index, 30);
        }

        /// <summary>
        /// Copies the contents of <paramref name="buffer"/> to this entry.
        /// </summary>
        /// <param name="buffer">The buffer to copy the contents from.</param>
        /// <param name="index">The starting byte index.</param>
        [DebuggerStepThrough]
        public override void CopyFrom(byte[] buffer, int index)
        {
            Array.Copy(buffer, index, FBuffer, 0x22, Math.Min(30, buffer.Length - index));
        }

        #endregion

        #region Constructors
        /// <overloads>Initializes a new instance of <see cref="BaseFileEntry"/>.</overloads>
        /// <summary>
        /// Initializes a new instance of <see cref="BaseFileEntry"/>.
        /// </summary>
        [DebuggerStepThrough]
        public BaseFileEntry(Int64 position, byte[] buffer)
            : base(position, buffer)
        {
        }
        /// <summary>
        /// Initializes a new instance of <see cref="BaseFileEntry"/> from an existing instace.
        /// </summary>
        /// <param name="value">The instance to copy.</param>
        /// <exception cref="ArgumentNullException">The argument <paramref name="value"/> is <see langword="null"/>.</exception>
        [DebuggerStepThrough]
        public BaseFileEntry(BaseFileEntry value)
            : base(value)
        {
        }
        #endregion
    }
}
